package circlequeue

type CircleQueue struct {
	cap         uint32
	front, rear uint32
	body        []interface{}
}

func (c *CircleQueue) GetLen() uint32 {
	return (c.rear - c.front) % c.cap
}

func (c *CircleQueue) IsFull() bool {
	return (c.rear+1)%c.cap == c.front
}

func (c *CircleQueue) IsEmpty() bool {
	return c.rear == c.front
}

func (c *CircleQueue) Enqueue(item interface{}) {
	if c.IsFull() {
		return
	}
	c.body = append(c.body, item)
	c.rear = (c.rear + 1) % c.cap
	c.rear++
}

func (c *CircleQueue) Dequeue() interface{} {
	if c.IsEmpty() {
		return nil
	}
	item := c.body[0]
	c.front = (c.front + 1) % c.cap
	c.front++
	return item
}

func NewCircleQueue() *CircleQueue {
	return &CircleQueue{
		cap:   100,
		rear:  0,
		front: 0,
		body:  []interface{}{},
	}
}

type OptionFunc func(*CircleQueue)

func WithOptionOfCap(cap uint32) OptionFunc {
	return func(c *CircleQueue) {
		c.cap = cap
	}
}

func NewCircleQueueV2(opts ...OptionFunc) *CircleQueue {
	defaultCircleQueue := &CircleQueue{
		cap:   100,
		rear:  0,
		front: 0,
		body:  []interface{}{},
	}

	for _, o := range opts {
		o(defaultCircleQueue)
	}
	return defaultCircleQueue
}
